/*
 * @Author: hongbin
 * @Date: 2023-05-26 18:39:07
 * @LastEditors: hongbin
 * @LastEditTime: 2023-05-26 20:19:32
 * @Description:导出gltf
 */
import { FC } from "react";
import * as THREE from "three";
import { ThreeHelper } from "@/ThreeHelper";
import Layout from "@/components/Three/Layout";
import { PointMaterial } from "@/shader/dot/material";
import { GLTFExporter } from "three/examples/jsm/exporters/GLTFExporter";
// import { DRACOLoader } from "three/examples/jsm/loaders/DRACOLoader";

interface IProps {}

const destroyEvent = [] as VoidFunction[];

const GltfExport: FC<IProps> = () => {
    return (
        <Layout
            seoTitle={"gltf导出"}
            init={init}
            destroy={() => destroyEvent.forEach((destroy) => destroy())}
        />
    );
};

export default GltfExport;

async function init(helper: ThreeHelper) {
    helper.addStats();
    helper.addAxis();
    helper.camera.position.set(0, 0, 30);
    helper.frameByFrame();
    helper.addGUI();
    helper.initLights();

    const group = new THREE.Group();
    helper.add(group);

    let particle: THREE.Points<
        THREE.BufferGeometry<THREE.NormalBufferAttributes>,
        THREE.PointsMaterial
    >;

    const guiControl = {
        link: "",
        size: 0.1,
        scale: 1,
        load: () => {
            if (guiControl.link.indexOf(".drc") > 0) {
                helper.dracoLoader.load(guiControl.link, (geo) => {
                    if (particle) {
                        particle.geometry.dispose();
                        particle.material.dispose();
                        group.remove(particle);
                    }
                    particle = new THREE.Points(
                        geo.scale(
                            guiControl.scale,
                            guiControl.scale,
                            guiControl.scale
                        ),
                        new THREE.PointsMaterial({ size: guiControl.size })
                    );
                    group.add(particle);
                });
            }
        },
        ExportGLTF: () => {
            const gltfExporter = new GLTFExporter();

            gltfExporter.parse(
                particle,
                function (result) {
                    console.log(result);
                    if (result instanceof ArrayBuffer) {
                        saveArrayBuffer(result, "scene.glb");
                    } else {
                        const output = JSON.stringify(result, null, 2);
                        saveString(output, "scene.gltf");
                    }
                },
                function (error) {
                    console.log("An error happened during parsing", error);
                },
                {
                    /**
                     * 默认false glb 二进制数据 ArrayBuffer
                     */
                    binary: false,
                }
            );
        },
    };

    function save(blob: Blob, filename: string) {
        const link = document.createElement("a");
        link.href = URL.createObjectURL(blob);
        link.download = filename;
        link.click();
        URL.revokeObjectURL(link.href);
    }

    function saveString(text: string, filename: string) {
        save(new Blob([text], { type: "text/plain" }), filename);
    }

    function saveArrayBuffer(buffer: ArrayBuffer, filename: string) {
        save(
            new Blob([buffer], { type: "application/octet-stream" }),
            filename
        );
    }

    helper.gui?.add(guiControl, "link").onFinishChange((v) => {
        console.log(v);
    });
    helper.gui?.add(guiControl, "load");
    helper.gui?.add(guiControl, "size", 0, 1);
    helper.gui?.add(guiControl, "scale", 0, 2);
    helper.gui?.add(guiControl, "ExportGLTF");
}
